import log from '../../../helpers/logger';
import { pushDiscordWebhook } from '../../../helpers/pushDiscordWebhook';
//import { validateLink } from '../../../helpers/dataValidation';

import {
  authorizedRouteHandler,
  ControllerMethodTypes,
  defaultRouteHandler,
} from '../../../../interfaces';
import { Request } from 'hyper-express';
import { showSelectedObjectKeys } from '../../../helpers/utilsJS';
import { db_connection } from '../../../../../prisma/generated/uctoo';
import { setExCache } from '../../../helpers/redis';
import { parseDbUrl } from '../../../helpers/utilsJS';
import { PrismaClient } from '../../../../../prisma/generated/uctoo'

const db = new PrismaClient({
  log: ['query', 'info', 'warn', 'error'],
});
import fs from 'fs';
import path from 'path';
import { execSync } from 'child_process';

type DatabaseType = 'postgresql' | 'mysql';
type ConnectionConfig = {
  databaseType: DatabaseType
  connection: {
    host: string
    port: number
    user: string
    password: string
    database: string
    ssl?: boolean
  }
}
  //#region AutoCreateCode
import {
  createDbConnection,
  deleteDbConnectionFromDatabase,
  deleteMultiDbConnectionFromDatabase,
  editDbConnectionInDatabase,
  editMultiDbConnectionInDatabase,
  getDbConnectionFromDatabase,
  getDbConnectionsFromDatabase,
  queryDbConnectionsFromDatabase,
  countDbConnections
} from '../../../services/uctoo/db_connection';

class uctooDbConnectionController {

  protected validateAndDestructureBody = async (
    req: Request,
    userId: string,
    actionType: ControllerMethodTypes
  ) => {
    const body = await req.json();
    const keysArray = Object.keys(body);       //如需自定义控制接收字段可在此定义，如['id','link','privacy_level','owner','description','group_id','stars'] ，默认接收所有提交字段
    const uctooDbConnection = showSelectedObjectKeys(body, keysArray) as db_connection;
    uctooDbConnection.creator = userId;

    return uctooDbConnection;
  };
  public add: authorizedRouteHandler = async (req, res) => {
    try {
      const user = res.locals.id.user;
      const uctooDbConnection = await this.validateAndDestructureBody(
        req,
        user,
        ControllerMethodTypes.ADD
      );
      if (!uctooDbConnection) return res.status(400).json({ errno: "40001", errmsg: '提交数据格式错误' });

      const createdDbConnection = await createDbConnection(uctooDbConnection);
      if (!createdDbConnection) return res.status(500).json({ errno: "50001", errmsg: "database query failed" });

      res.status(200).json(createdDbConnection);
    } catch (e) {
      log.error({ errno: "50000", errmsg: e.message, desc: e });
      return res.status(500).json({ errno: "50000", errmsg: e.message });
    }
  };
  public edit: authorizedRouteHandler = async (req, res) => {
    try {
      const user = res.locals.id.user;
      const body = await req.json();
      const { id,ids,force } = body;

      if(ids){
        const uctooDbConnection = await this.validateAndDestructureBody(
          req,
          user,
          ControllerMethodTypes.EDIT
        );
        if (!uctooDbConnection) return res.status(400).json({ errno: "40001", errmsg: '提交数据格式错误' });

        const editedDbConnection = await editMultiDbConnectionInDatabase(uctooDbConnection, JSON.parse(ids), user);
        
        if (typeof editedDbConnection === 'object' && 'success' in editedDbConnection) {
          if (!editedDbConnection.success) {
            return res.status(403).json({
              errno: "40301", 
              errmsg: editedDbConnection.reason,
              ...(editedDbConnection.dbConnectionId && { dbConnectionId: editedDbConnection.dbConnectionId })
            });
          }
          return res.status(200).json(editedDbConnection.data);
        }
        
        res.status(200).json(editedDbConnection);
      }else{
        const uctooDbConnection = await this.validateAndDestructureBody(
          req,
          user,
          ControllerMethodTypes.EDIT
        );
        if (!uctooDbConnection) return res.status(400).json({ errno: "40001", errmsg: '提交数据格式错误' });

        const editedDbConnection = await editDbConnectionInDatabase(uctooDbConnection, uctooDbConnection.id, user);
        
        if (typeof editedDbConnection === 'object' && 'success' in editedDbConnection) {
          if (!editedDbConnection.success) {
            return res.status(403).json({ errno: "40301", errmsg: editedDbConnection.reason });
          }
          return res.status(200).json(editedDbConnection.data);
        }
        res.status(200).json(editedDbConnection);
      }      
    } catch (e) {
      log.error({ errno: "50000", errmsg: e.message, desc: e });
      return res.status(500).json({ errno: "50000", errmsg: e.message });
    }
  };
  public delete: authorizedRouteHandler = async (req, res) => {
    try {
      const body = await req.json();
      const { id,ids,force } = body;
      const user = res.locals.id.user;

      if(ids){
        const deletionResult = await deleteMultiDbConnectionFromDatabase(JSON.parse(ids), force, user);
        
        if (typeof deletionResult === 'object' && 'success' in deletionResult) {
          if (!deletionResult.success) {
            return res.status(403).json({
              errno: "40301", 
              errmsg: deletionResult.reason,
              ...(deletionResult.dbConnectionId && { dbConnectionId: deletionResult.dbConnectionId })
            });
          }
          return res.status(200).json({ desc: '删除成功' });
        }
        
      }else{
        const deletionResult = await deleteDbConnectionFromDatabase(id, force, user);
        
        if (typeof deletionResult === 'object' && 'success' in deletionResult) {
          if (!deletionResult.success) {
            return res.status(403).json({ errno: "40301", errmsg: deletionResult.reason });
          }
          return res.status(200).json({ desc: '删除成功' });
        }
        
      }

      res.status(200).json({ desc: '删除成功' });
    } catch (e) {
      log.error({ errno: "50000", errmsg: e.message, desc: e });
      return res.status(500).json({ errno: "50000", errmsg: e.message });
    }
  };
  public getSingle: authorizedRouteHandler = async (req, res) => {
    try {
      const { id } = req.params;
      const user = res.locals.id.user;

      const dbConnectionFromDb = await getDbConnectionFromDatabase(id, user);
      if (!dbConnectionFromDb) {
        return res.status(404).json({ 
          errno: "40401", 
          errmsg: '未找到该实体或您没有权限访问' 
        });
      }

      res.status(200).json(dbConnectionFromDb);
    } catch (e) {
      log.error({ errno: "50000", errmsg: e.message, desc: e });
      return res.status(500).json({ errno: "50000", errmsg: e.message });
    }
  };
  public getMany: authorizedRouteHandler = async (req, res) => {
    try {
      const limit = parseInt(req.params.limit);
      const page = parseInt(req.params.page) || 0;
      const skip = parseInt(req.params.skip) || 0;
      const query = req.query;
      
      if (limit > 100) return res.status(400).json({ errno: "40002", errmsg: '请求数量不能超过100条' });
      if (isNaN(limit)) return res.status(400).json({ errno: "40003", errmsg: '请求数量必须是数字' });
      
      const user = res.locals.id.user;
      const totalCount = await countDbConnections(user);
      
      if (query) {
        const dbConnectionsFromDb = await queryDbConnectionsFromDatabase(limit, page, skip, query, user);
        if (!dbConnectionsFromDb) return res.status(404).json({ errno: "40401", errmsg: '未找到符合条件的实体' });

        res.status(200).json({
          currentPage: page,
          totalCount: totalCount,
          totalPage: Math.ceil(Number(totalCount)/limit),
          dbConnections: dbConnectionsFromDb
        });
      } else {
        const dbConnectionsFromDb = await getDbConnectionsFromDatabase(limit, skip, page, user);
        if (!dbConnectionsFromDb) return res.status(404).json({ errno: "40401", errmsg: '未找到符合条件的实体' });

        res.status(200).json({
          currentPage: page,
          totalCount:totalCount,
          totalPage: Math.ceil(Number(totalCount)/limit),
          dbConnections: dbConnectionsFromDb
        });
      }


    } catch (e) {
      log.error({ errno: "50000", errmsg: e.message, desc: e });
      return res.status(500).json({ errno: "50000", errmsg: e.message });
    }
  };
  //#endregion AutoCreateCode
  public asyncDatabaseUrl: authorizedRouteHandler = async (req, res) => {
    try {
      const user = res.locals.id.user;
      const body = await req.json();
      const { id, ids, force } = body;

      //读取env文件中的数据库连接信息
      const dbConfig = parseDbUrl(process.env.DATABASE_URL);
      //写入或更新数据库连接信息到数据库
      let uctooDbConnection = await db.db_connection.findFirst({
        where: { database_name: dbConfig.database }
      });
      if (uctooDbConnection) {
        //如果数据库连接信息已存在，则更新
        await db.db_connection.update({
          where: { id: uctooDbConnection.id },
          data: {
            user: dbConfig.user,
            password: dbConfig.password,
            host: dbConfig.host,
            port: dbConfig.port,
            provider: dbConfig.protocol,
            type: 'uctoo',
            creator: user
          }
        });
      } else {
        //如果数据库连接信息不存在，则创建
        uctooDbConnection = await db.db_connection.create({
          data: {
            database_name: dbConfig.database,
            user: dbConfig.user,
            password: dbConfig.password,
            host: dbConfig.host,
            port: dbConfig.port,
            provider: dbConfig.protocol,
            type: 'uctoo',
            creator: user
          }
        });
      }
      res.status(200).json(uctooDbConnection);
    } catch (e) {
      log.error({ err: e.message, desc: e });
      return res.status(500).json({ err: e.message, desc: e });
    }
  };

  public initConnection: authorizedRouteHandler = async (req, res) => {
    try {
      const uctoouser = res.locals.id.user;
      const body = await req.json();
      const { id, provider, user, password, host, port, database_name, ssl, type } = body;
      log.error(body);
      if (type == 'uctoo') {  //如果是uctoo主数据库，跳过不做处理

        log.error({ err: 'uctoo' });

      } else {  //如果是其他用户管理数据库
        //创建prisma用户数据库schema
        const sampleConfig: ConnectionConfig = {
          databaseType: provider,
          connection: {
            host: host,
            port: port,
            user: user,
            password: password,
            database: database_name
          }
        }
        log.error(sampleConfig);
        
        const tenantDir = path.join(__dirname, '../../../../../prisma', database_name)
        await this.ensureDir(tenantDir)

        // 写入 schema 文件
        const schemaPath = path.join(tenantDir, 'schema.prisma')
        
        // 新增文件存在性检查
        if (fs.existsSync(schemaPath)) {
          log.error('Schema文件已存在，跳过处理');
          return res.status(200).json({ message: 'Schema already exists' });
        }
        // 动态生成 Prisma schema
        const schemaContent = this.generateSchema(sampleConfig)
        await fs.writeFileSync(schemaPath, schemaContent)

        //从已连接数据库更新生成prisma用户数据库schema模型
        await this.pullPrismaDb(schemaPath);
        await this.generatePrismaClient(schemaPath);

        //数据库结构加入db_info
        await this.loadDbInfo(database_name);

        //生成服务器端API代码
        await this.batchCreateModuleFromDb(database_name);

        //生成web端代码
        await this.batchCreateViewFromDb(database_name);
        //




      }
      res.status(200).json({});
    } catch (e) {
      log.error({ err: e.message, desc: e });
      return res.status(500).json({ err: e.message, desc: e });
    }
  };

  private generateSchema(config: ConnectionConfig): string {
    const { databaseType, connection } = config
    const ssl = connection.ssl ? '?sslmode=require' : ''
    const { host, port, user, password, database } = connection

    return `
generator client {
  provider = "prisma-client"
  output   = "../generated/${database}"
  previewFeatures = ["typedSql"]
}

datasource db {
  provider = "${databaseType}"
  url      = "${this.getConnectionString(config)}"
}
    `.trim()
  }

  private getConnectionString(config: ConnectionConfig): string {
    const { databaseType, connection } = config
    const { host, port, user, password, database } = connection

    if (databaseType === 'postgresql') {
      return `postgresql://${user}:${password}@${host}:${port}/${database}`
    }

    if (databaseType === 'mysql') {
      return `mysql://${user}:${password}@${host}:${port}/${database}`
    }

    throw new Error('Unsupported database type')
  }

  private async ensureDir(dirPath: string) {
    await fs.mkdirSync(dirPath, { recursive: true })
  }

  private pullPrismaDb(schemaPath: string) {
    try {
      execSync(`npx prisma db pull --schema=${schemaPath}`, {
        stdio: 'inherit',
        env: {
          ...process.env
        }
      })
    } catch (error) {
      throw new Error(`Prisma生成失败: ${error.message}`);
    }
  }

  private loadDbInfo(dbName: string) {
    try {
      execSync(`npm run loadDbInfo ${dbName}`, {
        stdio: 'inherit',
        env: {
          ...process.env
        }
      })
    } catch (error) {
      throw new Error(`读取数据库结构失败: ${error.message}`);
    }
  }

  private batchCreateModuleFromDb(dbName: string) {
    try {
      execSync(`npm run batchCreateModuleFromDb ${dbName} true false`, {
        stdio: 'inherit',
        env: {
          ...process.env
        }
      })
    } catch (error) {
      throw new Error(`生成服务器端API代码: ${error.message}`);
    }
  }

  private batchCreateViewFromDb(dbName: string) {
    try {
      execSync(`npm run batchCreateViewFromDb ${dbName} false`, {
        stdio: 'inherit',
        env: {
          ...process.env
        }
      })
    } catch (error) {
      throw new Error(`生成web端代码: ${error.message}`);
    }
  }

  private generatePrismaClient(schemaPath: string) {
    try {
      execSync(`npx prisma generate --schema=${schemaPath}`, {
        stdio: 'inherit',
        env: {
          ...process.env
        }
      })
    } catch (error) {
      throw new Error(`Prisma Client generation failed: ${error.message}`)
    }
  }







}
export default uctooDbConnectionController;
